package com.investment.advisor.service.impl;

import com.investment.advisor.dto.UserDTO;
import com.investment.advisor.dto.RegisterRequest;
import com.investment.advisor.dto.LoginRequest;
import com.investment.advisor.entity.LoginRecord;
import com.investment.advisor.entity.User;
import com.investment.advisor.repository.LoginRecordRepository;
import com.investment.advisor.repository.UserRepository;
import com.investment.advisor.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityNotFoundException;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private LoginRecordRepository loginRecordRepository;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public UserDTO register(RegisterRequest request) {
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new IllegalArgumentException("用户名已存在");
        }
        User user = new User();
        user.setUsername(request.getUsername());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setEmail(request.getEmail());
        user.setRole("USER");
        user.setCreateTime(java.time.LocalDateTime.now());
        user.setUpdateTime(java.time.LocalDateTime.now());
        userRepository.save(user);

        UserDTO dto = new UserDTO();
        BeanUtils.copyProperties(user, dto);
        return dto;
    }

    @Override
    @Transactional
    public UserDTO login(LoginRequest request, HttpServletRequest httpRequest) {
        User user = userRepository.findByUsername(request.getUsername())
                .orElseThrow(() -> new RuntimeException("User not found"));

        if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
            LoginRecord loginRecord = new LoginRecord();
            loginRecord.setUserId(user.getId());
            loginRecord.setLoginTime(LocalDateTime.now());
            loginRecord.setLoginStatus("OFFLINE");
            loginRecord.setIpAddress(getClientIp(httpRequest));
            loginRecord.setDeviceInfo(httpRequest.getHeader("User-Agent"));
            loginRecordRepository.save(loginRecord);
            throw new RuntimeException("Invalid password");
        }

        LoginRecord lastLogin = loginRecordRepository.findTopByUserIdOrderByLoginTimeDesc(user.getId());
        if (lastLogin != null && lastLogin.getLogoutTime() == null) {
            lastLogin.setLogoutTime(LocalDateTime.now());
            lastLogin.setLoginStatus("OFFLINE");
            loginRecordRepository.save(lastLogin);
        }

        LoginRecord loginRecord = new LoginRecord();
        loginRecord.setUserId(user.getId());
        loginRecord.setLoginTime(LocalDateTime.now());
        loginRecord.setLoginStatus("ONLINE");
        loginRecord.setIpAddress(getClientIp(httpRequest));
        loginRecord.setDeviceInfo(httpRequest.getHeader("User-Agent"));
        loginRecordRepository.save(loginRecord);

        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(user, userDTO);
        return userDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void logout(Long userId, String deviceInfo) {
        System.out.println("Processing logout for user: " + userId + " from device: " + deviceInfo);
        try {
            if (deviceInfo != null) {
                // 如果提供了设备信息，只登出该设备的会话
                LoginRecord activeLogin = loginRecordRepository.findActiveLoginRecordForUpdate(userId)
                    .filter(record -> deviceInfo.equals(record.getDeviceInfo()))
                    .orElse(null);

                if (activeLogin != null) {
                    System.out.println("Found matching login record: " + activeLogin.getId() + ", status: " + activeLogin.getLoginStatus());
                    if (activeLogin.getLogoutTime() == null) {
                        activeLogin.setLogoutTime(LocalDateTime.now());
                        activeLogin.setLoginStatus("OFFLINE");
                        loginRecordRepository.save(activeLogin);
                        System.out.println("Updated login record with logout time and OFFLINE status");
                    } else {
                        System.out.println("Login record already has logout time set");
                    }
                } else {
                    System.out.println("No matching active login record found for device");
                }
            } /*else {
                // 如果没有提供设备信息，登出所有活动会话
                List<LoginRecord> activeLogins = loginRecordRepository.findAllActiveLoginRecords(userId);
                for (LoginRecord login : activeLogins) {
                    login.setLogoutTime(LocalDateTime.now());
                    login.setLoginStatus("OFFLINE");
                    loginRecordRepository.save(login);
                    System.out.println("Updated login record: " + login.getId() + " with logout time and OFFLINE status");
                }
                if (activeLogins.isEmpty()) {
                    System.out.println("No active login records found for user: " + userId);
                }
            }*/
        } catch (Exception e) {
            System.err.println("Error during logout process: " + e.getMessage());
            throw e;
        }
    }

    @Override
    public List<UserDTO> getOnlineUsers() {
        return loginRecordRepository.findOnlineUsers().stream()
                .map(loginRecord -> {
                    UserDTO dto = new UserDTO();
                    User user = loginRecord.getUser();
                    dto.setId(user.getId());
                    dto.setUsername(user.getUsername());
                    dto.setEmail(user.getEmail());
                    dto.setRole(user.getRole());
                    dto.setLoginTime(loginRecord.getLoginTime());
                    dto.setIpAddress(loginRecord.getIpAddress());
                    dto.setDeviceInfo(loginRecord.getDeviceInfo());
                    return dto;
                })
                .collect(Collectors.toList());
    }

    @Override
    public long getOnlineUserCount() {
        return loginRecordRepository.countOnlineUsers();
    }

    private String getClientIp(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            return xForwardedFor.split(",")[0].trim();
        }
        return request.getRemoteAddr();
    }
} 